package com.qupai.lib_base.widget.sticker

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.MotionEventCompat
import com.qupai.lib_base.widget.sticker.utils.PointUtils.getBitmapPoints

/**
 * 作者：ZhouYou
 * 日期：2016/12/2.
 */
class StickerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatImageView(context, attrs, defStyleAttr) {
    private var context: Context? = null

    /**
     * 获取贴纸对象
     *
     * @return
     */
    // 被操作的贴纸对象
    lateinit var sticker: Sticker

    // 手指按下时图片的矩阵
    private val downMatrix = Matrix()

    // 手指移动时图片的矩阵
    private val moveMatrix = Matrix()

    // 多点触屏时的中心点
    private var midPoint: PointF? = PointF()

    // 图片的中心点坐标
    private var imageMidPoint: PointF? = PointF()

    // 旋转操作图片
    private var rotateIcon: StickerActionIcon? = null

    // 缩放操作图片
    private var zoomIcon: StickerActionIcon? = null

    // 缩放操作图片
    private var removeIcon: StickerActionIcon? = null

    // 绘制图片的边框
    private var paintEdge: Paint? = null

    // 触控模式
    private var mode = 0

    // 是否正在处于编辑
    private var isEdit = true

    // 贴纸的操作监听
    private var listener: OnStickerActionListener? = null
    fun setOnStickerActionListener(listener: OnStickerActionListener?) {
        this.listener = listener
    }

    private fun init(context: Context) {
        this.context = context
        scaleType = ScaleType.MATRIX
        rotateIcon = StickerActionIcon(context)
        zoomIcon = StickerActionIcon(context)
        removeIcon = StickerActionIcon(context)
        paintEdge = Paint()
        paintEdge!!.color = Color.BLACK
        paintEdge!!.alpha = 170
        paintEdge!!.isAntiAlias = true
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (changed) {
            sticker.matrix.postTranslate(((width - sticker.stickerWidth) / 2).toFloat(), ((height - sticker.stickerHeight) / 2).toFloat())
        }
    }

    override fun onDraw(canvas: Canvas) {
        sticker.draw(canvas)
        val points = getBitmapPoints(sticker.srcImage!!, sticker.matrix)
        val x1 = points[0]
        val y1 = points[1]
        val x2 = points[2]
        val y2 = points[3]
        val x3 = points[4]
        val y3 = points[5]
        val x4 = points[6]
        val y4 = points[7]
        if (isEdit) {
            // 画边框
            canvas.drawLine(x1, y1, x2, y2, paintEdge!!)
            canvas.drawLine(x2, y2, x4, y4, paintEdge!!)
            canvas.drawLine(x4, y4, x3, y3, paintEdge!!)
            canvas.drawLine(x3, y3, x1, y1, paintEdge!!)
            // 画操作按钮图片
            rotateIcon!!.draw(canvas, x2, y2)
            zoomIcon!!.draw(canvas, x3, y3)
            removeIcon!!.draw(canvas, x1, y1)
        }
    }

    // 手指按下屏幕的X坐标
    private var downX = 0f

    // 手指按下屏幕的Y坐标
    private var downY = 0f

    // 手指之间的初始距离
    private var oldDistance = 0f

    // 手指之间的初始角度
    private var oldRotation = 0f

    init {
        init(context)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        val action = MotionEventCompat.getActionMasked(event)
        var isStickerOnEdit = true
        when (action) {
            MotionEvent.ACTION_DOWN -> {
                downX = event.x
                downY = event.y
                // 删除操作
                if (removeIcon!!.isInActionCheck(event)) {
                    if (listener != null) {
                        listener!!.onDelete()
                    }
                } else if (rotateIcon!!.isInActionCheck(event)) {
                    mode = ActionMode.ROTATE
                    downMatrix.set(sticker.matrix)
                    imageMidPoint = sticker.getImageMidPoint(downMatrix)
                    oldRotation = sticker.getSpaceRotation(event, imageMidPoint!!)
                    Log.d("onTouchEvent", "旋转手势")
                } else if (zoomIcon!!.isInActionCheck(event)) {
                    mode = ActionMode.ZOOM_SINGLE
                    downMatrix.set(sticker.matrix)
                    imageMidPoint = sticker.getImageMidPoint(downMatrix)
                    oldDistance = sticker.getSingleTouchDistance(event, imageMidPoint!!)
                    Log.d("onTouchEvent", "单点缩放手势")
                } else if (isInStickerArea(sticker, event)) {
                    mode = ActionMode.TRANS
                    downMatrix.set(sticker.matrix)
                    Log.d("onTouchEvent", "平移手势")
                } else {
                    isStickerOnEdit = false
                }
            }
            MotionEvent.ACTION_POINTER_DOWN -> {
                mode = ActionMode.ZOOM_MULTI
                oldDistance = sticker.getMultiTouchDistance(event)
                midPoint = sticker.getMidPoint(event)
                downMatrix.set(sticker.matrix)
            }
            MotionEvent.ACTION_MOVE ->                 // 单点旋转
                when (mode) {
                    ActionMode.ROTATE -> {
                        moveMatrix.set(downMatrix)
                        val deltaRotation = sticker.getSpaceRotation(event, imageMidPoint!!) - oldRotation
                        moveMatrix.postRotate(deltaRotation, imageMidPoint!!.x, imageMidPoint!!.y)
                        sticker.matrix.set(moveMatrix)
                        invalidate()
                    }
                    ActionMode.ZOOM_SINGLE -> {
                        moveMatrix.set(downMatrix)
                        val scale = sticker.getSingleTouchDistance(event, imageMidPoint!!) / oldDistance
                        moveMatrix.postScale(scale, scale, imageMidPoint!!.x, imageMidPoint!!.y)
                        sticker.matrix.set(moveMatrix)
                        invalidate()
                    }
                    ActionMode.ZOOM_MULTI -> {
                        moveMatrix.set(downMatrix)
                        val scale = sticker.getMultiTouchDistance(event) / oldDistance
                        moveMatrix.postScale(scale, scale, midPoint!!.x, midPoint!!.y)
                        sticker.matrix.set(moveMatrix)
                        invalidate()
                    }
                    ActionMode.TRANS -> {
                        moveMatrix.set(downMatrix)
                        moveMatrix.postTranslate(event.x - downX, event.y - downY)
                        sticker.matrix.set(moveMatrix)
                        invalidate()
                    }
                }
            MotionEvent.ACTION_POINTER_UP, MotionEvent.ACTION_UP -> {
                mode = ActionMode.NONE
                midPoint = null
                imageMidPoint = null
            }
            else -> {}
        }
        if (isStickerOnEdit && listener != null) {
            listener!!.onEdit(this)
        }
        return isStickerOnEdit
    }

    /**
     * 判断手指是否在操作区域内
     *
     * @param sticker
     * @param event
     * @return
     */
    private fun isInStickerArea(sticker: Sticker, event: MotionEvent): Boolean {
        val dst = sticker.srcImageBound
        return dst.contains(event.x, event.y)
    }

    /**
     * 添加贴纸
     *
     * @param resId
     */
    override fun setImageResource(resId: Int) {
        sticker = Sticker(BitmapFactory.decodeResource(context!!.resources, resId))
    }

    override fun setImageBitmap(bm: Bitmap) {
        sticker = Sticker(bm)
    }

    /**
     * 设置是否贴纸正在处于编辑状态
     *
     * @param edit
     */
    fun setEdit(edit: Boolean) {
        isEdit = edit
        postInvalidate()
    }

    /**
     * 设置旋转操作的图片
     *
     * @param rotateRes
     */
    fun setRotateRes(rotateRes: Int) {
        rotateIcon!!.setSrcIcon(rotateRes)
    }

    /**
     * 设置缩放操作的图片
     *
     * @param zoomRes
     */
    fun setZoomRes(zoomRes: Int) {
        zoomIcon!!.setSrcIcon(zoomRes)
    }

    /**
     * 设置删除操作的图片
     *
     * @param removeRes
     */
    fun setRemoveRes(removeRes: Int) {
        removeIcon!!.setSrcIcon(removeRes)
    }
}